#include "Server.h"
#include "base.qpb.h"
#include "gateway.qpb.h"
#include "friend.qpb.h"
#include "file.qpb.h"
#include "speech.qpb.h"
#include "transmit.qpb.h"
#include "message.qpb.h"
#include "user.qpb.h"
#include "notify.qpb.h"
#include "util.h"

////////////////////////////////////
/// 一些辅助函数
////////////////////////////////////
LYZ::UserInfo makeUserInfo(int index, const QByteArray &avatar)
{
    LYZ::UserInfo userInfo;
    userInfo.setUserId(QString::number(2000 + index));
    userInfo.setNickname("张三" + QString::number(index));
    userInfo.setDescription("adsdasf");
    userInfo.setMail("afsfsfasfs");
    userInfo.setAvatar(avatar);
    return userInfo;
}

LYZ::MessageInfo makeTextMessageInfo(int index, const QByteArray &avatar)
{
    LYZ::MessageInfo msgInfo;
    msgInfo.setMessageId(QString::number(3000 + index));
    msgInfo.setChatSessionId(QString::number(1000 + index));
    msgInfo.setTimestamp(getTime());
    msgInfo.setSender(makeUserInfo(index, avatar));

    LYZ::StringMessageInfo stringMsgInfo;
    stringMsgInfo.setContent("消息" + QString::number(index));

    LYZ::MessageContent msgCon;
    msgCon.setMessageType(LYZ::MessageTypeGadget::STRING);
    msgCon.setStringMessage(stringMsgInfo);

    msgInfo.setMessage(msgCon);

    return msgInfo;
}

////////////////////////////////////
/// HTTP 服务器
////////////////////////////////////
HttpServer *HttpServer::instance = nullptr;

HttpServer::HttpServer()
{

}

HttpServer *HttpServer::getInstance()
{
    if (instance == nullptr)
        instance = new HttpServer();
    return instance;
}

bool HttpServer::init()
{
    // 绑定和监听
    int ret = _httpServer.listen(QHostAddress::Any, 8000);

    // 配置路由
    _httpServer.route("/ping", [](const QHttpServerRequest &req){
        DEBUG() << "[http] 收到 ping 请求";
        return "pong";
    });

    _httpServer.route("/service/user/get_user_info", [=](const QHttpServerRequest &req){
        return this->getUserInfo(req);
    });

    _httpServer.route("/service/friend/get_friend_list", [=](const QHttpServerRequest &req){
        return this->getFriendList(req);
    });

    _httpServer.route("/service/friend/get_chat_session_list", [=](const QHttpServerRequest &req){
        return this->getChatSessionList(req);
    });

    _httpServer.route("/service/friend/get_pending_friend_events", [=](const QHttpServerRequest &req){
        return this->getApplyList(req);
    });

    _httpServer.route("/service/message_storage/get_recent", [=](const QHttpServerRequest &req){
        return this->getRecentMsg(req);
    });

    _httpServer.route("/service/transmit/new_message", [=](const QHttpServerRequest &req){
        return this->newMsg(req);
    });

    _httpServer.route("/service/user/set_nickname", [=](const QHttpServerRequest &req){
        return this->setNickname(req);
    });
    return ret == 8000;
}

QHttpServerResponse HttpServer::getUserInfo(const QHttpServerRequest &req)
{
    LYZ::GetUserInfoReq request;
    request.deserialize(&_serializer, req.body());
    DEBUG() << "[REQ 获取用户信息] requestId: " << request.requestId() << ", loginSessionId: " << request.sessionId();

    LYZ::GetUserInfoRsp response;
    response.setRequestId(request.requestId());
    response.setSuccess(true);
    response.setErrmsg("");

    LYZ::UserInfo userInfo = makeUserInfo(0, loadFileToByteArray(":/resource/image/defaultAvatar.png"));;
    response.setUserInfo(userInfo);

    QByteArray body = response.serialize(&_serializer);

    QHttpServerResponse rsp(body, QHttpServerResponse::StatusCode::Ok);
    rsp.setHeader("Content-Type", "application/x-protobuf");

    return rsp;
}

QHttpServerResponse HttpServer::getFriendList(const QHttpServerRequest &req)
{
    LYZ::GetFriendListReq request;
    request.deserialize(&_serializer, req.body());
    DEBUG() << "[REQ 好友列表] requestId: " << request.requestId() << ", loginSessionId: " << request.sessionId();

    LYZ::GetFriendListRsp response;
    response.setRequestId(request.requestId());
    response.setSuccess(true);
    response.setErrmsg("");

    QByteArray avatar = loadFileToByteArray(":/resource/image/defaultAvatar.png");
    for (int i = 0; i < 30; i++)
    {
        LYZ::UserInfo userInfo = makeUserInfo(i, avatar);
        response.friendList().push_back(userInfo);
    }

    QByteArray body = response.serialize(&_serializer);

    QHttpServerResponse rsp(body, QHttpServerResponse::StatusCode::Ok);
    rsp.setHeader("Content-Type", "application/x-protobuf");

    return rsp;
}

QHttpServerResponse HttpServer::getChatSessionList(const QHttpServerRequest &req)
{
    LYZ::GetChatSessionListReq request;
    request.deserialize(&_serializer, req.body());
    DEBUG() << "[REQ 会话列表] requestId: " << request.requestId() << ", loginSessionId: " << request.sessionId();

    LYZ::GetChatSessionListRsp response;
    response.setRequestId(request.requestId());
    response.setSuccess(true);
    response.setErrmsg("");

    QByteArray avatar = loadFileToByteArray(":/resource/image/defaultAvatar.png");
    for (int i = 0; i < 30; i++)
    {
        LYZ::ChatSessionInfo chatSessionInfo;
        chatSessionInfo.setChatSessionId(QString::number(1000 + i));
        chatSessionInfo.setChatSessionName("会话" + QString::number(i));
        chatSessionInfo.setSingleChatFriendId(QString::number(2000 + i));
        chatSessionInfo.setAvatar(avatar);

        LYZ::MessageInfo msgInfo = makeTextMessageInfo(i, avatar);
        chatSessionInfo.setPrevMessage(msgInfo);
        response.chatSessionInfoList().push_back(chatSessionInfo);
    }

    QByteArray body = response.serialize(&_serializer);

    QHttpServerResponse rsp(body, QHttpServerResponse::StatusCode::Ok);
    rsp.setHeader("Content-Type", "application/x-protobuf");

    return rsp;
}

QHttpServerResponse HttpServer::getApplyList(const QHttpServerRequest &req)
{
    LYZ::GetPendingFriendEventListReq request;
    request.deserialize(&_serializer, req.body());
    DEBUG() << "[REQ 申请列表] requestId: " << request.requestId() << ", loginSessionId: " << request.sessionId();

    LYZ::GetPendingFriendEventListRsp response;
    response.setRequestId(request.requestId());
    response.setSuccess(true);
    response.setErrmsg("");

    QByteArray avatar = loadFileToByteArray(":/resource/image/defaultAvatar.png");
    for (int i = 0; i < 30; i++)
    {
        LYZ::UserInfo userInfo = makeUserInfo(i, avatar);
        LYZ::FriendEvent ev;
        ev.setEventId(QString::number(1000 + i));
        ev.setSender(userInfo);
        response.event().push_back(ev);
    }

    QByteArray body = response.serialize(&_serializer);

    QHttpServerResponse rsp(body, QHttpServerResponse::StatusCode::Ok);
    rsp.setHeader("Content-Type", "application/x-protobuf");

    return rsp;
}

QHttpServerResponse HttpServer::getRecentMsg(const QHttpServerRequest &req)
{
    LYZ::GetRecentMsgReq request;
    request.deserialize(&_serializer, req.body());
    DEBUG() << "[REQ 获取会话最近消息] requestId: " << request.requestId() << ", loginSessionId: " << request.sessionId();

    LYZ::GetRecentMsgRsp response;
    response.setRequestId(request.requestId());
    response.setSuccess(true);
    response.setErrmsg("");

    QByteArray avatar = loadFileToByteArray(":/resource/image/defaultAvatar.png");
    for (int i = 0; i < 30; i++)
    {
        LYZ::MessageInfo msgInfo = makeTextMessageInfo(i, avatar);
        msgInfo.setChatSessionId(request.chatSessionId());
        response.msgList().push_back(msgInfo);
    }

    QByteArray body = response.serialize(&_serializer);

    QHttpServerResponse rsp(body, QHttpServerResponse::StatusCode::Ok);
    rsp.setHeader("Content-Type", "application/x-protobuf");

    return rsp;
}

QHttpServerResponse HttpServer::newMsg(const QHttpServerRequest &req)
{
    LYZ::NewMessageReq request;
    request.deserialize(&_serializer, req.body());
    DEBUG() << "[REQ 获取会话最近消息] requestId: " << request.requestId() << ", loginSessionId: " << request.sessionId();

    LYZ::NewMessageRsp response;
    response.setRequestId(request.requestId());
    response.setSuccess(true);
    response.setErrmsg("");

    QByteArray body = response.serialize(&_serializer);

    QHttpServerResponse rsp(body, QHttpServerResponse::StatusCode::Ok);
    rsp.setHeader("Content-Type", "application/x-protobuf");

    return rsp;
}

QHttpServerResponse HttpServer::setNickname(const QHttpServerRequest &req)
{
    LYZ::SetUserNicknameReq request;
    request.deserialize(&_serializer, req.body());
    DEBUG() << "[REQ 设置用户昵称] requestId: " << request.requestId() << ", loginSessionId: " << request.sessionId();

    LYZ::SetUserNicknameRsp response;
    response.setRequestId(request.requestId());
    response.setSuccess(true);
    response.setErrmsg("");

    QByteArray body = response.serialize(&_serializer);

    QHttpServerResponse rsp(body, QHttpServerResponse::StatusCode::Ok);
    rsp.setHeader("Content-Type", "application/x-protobuf");

    return rsp;
}

////////////////////////////////////
/// WebSocket 服务器
////////////////////////////////////
WebSocketServer *WebSocketServer::instance = nullptr;

WebSocketServer::WebSocketServer() :_webSocketServer("webSocket server", QWebSocketServer::NonSecureMode)
{

}

WebSocketServer *WebSocketServer::getInstance()
{
    if (instance == nullptr)
        instance = new WebSocketServer();
    return instance;
}

bool WebSocketServer::init()
{
    // 连接信号槽
    connect(&_webSocketServer, &QWebSocketServer::newConnection, this, [=](){
        DEBUG() << "[webSocket] 链接建立成功";
        QWebSocket *socket = _webSocketServer.nextPendingConnection();

        connect(socket, &QWebSocket::disconnected, this, [=](){
            DEBUG() << "[webSocket] 链接断开";
            disconnect(this, &WebSocketServer::sendText, this, nullptr);
        });

        connect(socket, &QWebSocket::errorOccurred, this, [=](){
            DEBUG() << "[webSocket] 链接建立有误";
        });

        connect(socket, &QWebSocket::textMessageReceived, this, [=](const QString& msg){
            DEBUG() << "websocket 收到文本消息: " << msg;
        });


        connect(socket, &QWebSocket::binaryMessageReceived, this, [=](const QByteArray &msg){
            DEBUG() << "websocket 收到二进制消息: " << msg.length();
        });

        connect(this, &WebSocketServer::sendText, this, [=](){
            if (socket == nullptr || !socket->isValid())
            {
                return;
            }

            LYZ::NotifyNewMessage newMessage;
            QByteArray avatar = loadFileToByteArray(":/resource/image/defaultAvatar.png");
            newMessage.setMessageInfo(makeTextMessageInfo(_messageIndex++, avatar));

            LYZ::NotifyMessage notifyMessage;
            notifyMessage.setNotifyType(LYZ::NotifyTypeGadget::NotifyType::CHAT_MESSAGE_NOTIFY);
            notifyMessage.setNewMessageInfo(newMessage);

            QByteArray body = notifyMessage.serialize(&_serializer);

            socket->sendBinaryMessage(body);

            DEBUG() << "发送文本消息响应";
        });
    });

    return _webSocketServer.listen(QHostAddress::Any, 8001);
}


